package org.codefinger.dao.util;

import java.io.Closeable;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.Arrays;

public class TLStringBuilder implements Closeable {

	private static final ThreadLocal<Reference<char[]>>	LOCAL_BUFFER	= new ThreadLocal<Reference<char[]>>();

	private char[]										value;

	private int											count;

	public TLStringBuilder() {
		Reference<char[]> ref = LOCAL_BUFFER.get();

		if (ref != null) {
			value = ref.get();
			LOCAL_BUFFER.set(null);
		}

		if (value == null) {
			value = new char[1024];
		}
	}

	public void append(String str) {
		int len = str.length();
		ensureCapacityInternal(count + len);
		str.getChars(0, len, value, count);
		count += len;
	}

	public void append(char cha) {
		ensureCapacityInternal(count + 1);
		value[count++] = cha;
	}

	public TLStringBuilder back(int size) {
		count = size;
		return this;
	}

	public int length() {
		return count;
	}

	public char[] value() {
		return value;
	}

	@Override
	public String toString() {
		return new String(value, 0, count);
	}

	@Override
	public void close() {
		if (value.length <= 8192) {
			LOCAL_BUFFER.set(new SoftReference<char[]>(value));
		}
	}

	private void ensureCapacityInternal(int minimumCapacity) {
		if (minimumCapacity - value.length > 0) {
			expandCapacity(minimumCapacity);
		}
	}

	private void expandCapacity(int minimumCapacity) {
		int newCapacity = value.length * 2 + 2;
		if (newCapacity - minimumCapacity < 0) {
			newCapacity = minimumCapacity;
		}
		if (newCapacity < 0) {
			if (minimumCapacity < 0) {
				throw new OutOfMemoryError();
			}
			newCapacity = Integer.MAX_VALUE;
		}
		value = Arrays.copyOf(value, newCapacity);
	}

}
